import { Vector2 } from 'three';
import AbstractHandler, { HandlerEvent } from './AbstractHandler';

type DragEvent = HandlerEvent<'dragend'>;

class DragPan extends AbstractHandler<DragEvent> {
  private _lastPoint?: Vector2;

  mousedown(e: MouseEvent) {
    if (e.buttons !== 1 || this._state === 'disable') return;
    this._lastPoint = new Vector2(e.clientX, e.clientY);
  }

  mousemove(e: MouseEvent) {
    if (!this._lastPoint || e.buttons !== 1) return;
    const current = new Vector2(e.clientX, e.clientY);
    // for inertia
    this._handlerManager.getInertia().record({ pan: current });

    const engine = this._handlerManager.getView().getEngine();
    const camera = engine.getCamera();
    const world = camera.screenToWorld(this._lastPoint);
    camera.setCenterAtPoint(world, current);
    engine.render();
    this._lastPoint = current;
  }

  mouseup(e: MouseEvent) {
    this._end(e);
  }

  mouseleave(e: MouseEvent) {
    this._end(e);
  }

  private _end(e: MouseEvent | TouchEvent) {
    if (!this._lastPoint) return;
    delete this._lastPoint;
    this._handlerManager.inertiaEasing();
    this.dispatchEvent({
      type: 'dragend',
      event: e,
    });
  }
}

export default DragPan;
